package com.iwomy.secureplat.platform.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.iwomy.secureplat.admin.api.feign.RemoteDeptService;
import com.iwomy.secureplat.common.data.datascope.DataScope;
import com.iwomy.secureplat.common.security.util.SecurityUtils;
import com.iwomy.secureplat.platform.dto.AlarmFaultLoggingDTO;
import com.iwomy.secureplat.platform.entity.*;
import com.iwomy.secureplat.platform.mapper.BasicDeviceAttributeMapper;
import com.iwomy.secureplat.platform.mapper.BasicDeviceMapper;
import com.iwomy.secureplat.platform.mapper.BasicDeviceModelMapper;
import com.iwomy.secureplat.platform.mapper.BasicInstallLocationMapper;
import com.iwomy.secureplat.platform.service.*;
import com.iwomy.secureplat.platform.utils.DataScopeUtils;
import com.iwomy.secureplat.platform.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ScreenDataServiceImpl implements ScreenDataService {

	@Resource
	private AlarmLoggingService alarmLoggingService;

	@Resource
	private AlarmFaultLoggingService alarmFaultLoggingService;

	@Resource
	private BasicInstallLocationService basicInstallLocationService;

	@Resource
	private BasicDeviceService basicDeviceService;

	@Resource
	private BasicDeviceTypeService basicDeviceTypeService;

	@Resource
	private DeviceEventReportService deviceEventReportService;

	@Resource
	private RemoteDeptService remoteDeptService;

	@Resource
	private BasicInstallLocationMapper basicInstallLocationMapper;

	@Resource
	private BasicDeviceMapper basicDeviceMapper;

	@Resource
	private BasicDeviceAttributeMapper basicDeviceAttributeMapper;

	@Resource
	private BasicDeviceModelMapper basicDeviceModelMapper;


	//今日报警及故障
	@Override
	public ScreenDataVO getTodayAlarmAndFault() {
		ScreenDataVO todayAlarm = this.getTodayAlarm();
		ScreenDataVO todayFault = this.getTodayFault();

		ScreenDataVO screenDataVO = new ScreenDataVO();
		screenDataVO.setTodayAlarmNum(todayAlarm.getTodayAlarmNum());
		screenDataVO.setTodayAlarmHandledNum(todayAlarm.getTodayAlarmHandledNum());
		screenDataVO.setTodayAlarmHandledPer(todayAlarm.getTodayAlarmHandledPer());
		screenDataVO.setTodayFaultNum(todayFault.getTodayFaultNum());
		screenDataVO.setTodayFaultHandledNum(todayFault.getTodayFaultHandledNum());
		screenDataVO.setTodayFaultHandledPer(todayFault.getTodayFaultHandledPer());
		return screenDataVO;
	}

	//未处理报警
	@Override
	public List<ScreenDataVO> getUnprocessedAlarm() {
		LambdaQueryWrapper<BasicInstallLocationEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicInstallLocationEntity> list = basicInstallLocationService.listByScope(queryWrapper, new DataScope());
		List<Long> installLocationId = list.stream().map(BasicInstallLocationEntity::getId).collect(Collectors.toList());

		if (ObjectUtil.isEmpty(installLocationId)) {
			return null;
		}
		MPJLambdaWrapper<BasicInstallLocationEntity> wrapper = createScreenUnprocessedAlarmWrapper();
		wrapper.in(BasicInstallLocationEntity::getId, installLocationId);
		List<ScreenDataVO> dataVOS = basicInstallLocationMapper.selectJoinList(ScreenDataVO.class, wrapper);

		return dataVOS;
	}

	//未处理故障
	@Override
	public List<ScreenDataVO> getUnprocessedFault() {
		LambdaQueryWrapper<BasicInstallLocationEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicInstallLocationEntity> list = basicInstallLocationService.listByScope(queryWrapper, new DataScope());
		List<Long> installLocationId = list.stream().map(BasicInstallLocationEntity::getId).collect(Collectors.toList());

		if (ObjectUtil.isEmpty(installLocationId)) {
			return null;
		}

		MPJLambdaWrapper<BasicInstallLocationEntity> wrapper = createScreenUnprocessedFaultWrapper();
		wrapper.in(BasicInstallLocationEntity::getId, installLocationId);
		List<ScreenDataVO> dataVOS = basicInstallLocationMapper.selectJoinList(ScreenDataVO.class, wrapper);

		return dataVOS;
	}

	//大屏地图
	@Override
	public List<ScreenMapPointVO> mapPoint() {
		LambdaQueryWrapper<BasicInstallLocationEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicInstallLocationEntity> list = basicInstallLocationService.listByScope(queryWrapper, new DataScope());
		List<Long> installLocationId = list.stream().map(BasicInstallLocationEntity::getId).collect(Collectors.toList());

		if (ObjectUtil.isEmpty(installLocationId)) {
			return null;
		}


		MPJLambdaWrapper<BasicDeviceEntity> screenMapPointWrapper = createScreenMapPointWrapper();
		screenMapPointWrapper.in(BasicInstallLocationEntity::getId, installLocationId);
		screenMapPointWrapper.disableSubLogicDel();
		List<ScreenMapPointVO> dataVOS = basicDeviceMapper.selectJoinList(ScreenMapPointVO.class, screenMapPointWrapper);

		dataVOS.stream().forEach(e -> {

			//为地图坐标的属性赋值
			e.setRemarks(getDeviceAttribute(e.getDeviceTypeId()));

			//	为地图坐标设置报警原因
			if (e.getDeviceState() == 40) {
				e.setAlarmCauses(getPointAlarm(e.getId()).getAlarmCauses());
				e.setAlarmId(getPointAlarm(e.getId()).getId());
				e.setAlarmCreateTime(getPointAlarm(e.getId()).getCreateTime());
			}
			//	为地图坐标设置故障原因
			if (e.getDeviceState() == 30) {
				e.setFaultCauses(getPointFault(e.getId()).getAlarmCauses());
				e.setFaultId(getPointFault(e.getId()).getId());
				e.setFaultCreateTime(getPointFault(e.getId()).getCreateTime());
			}

			//为地图坐标设置设备型号名
			e.setDeviceModelName(getModelName(e.getDeviceModelId()));
		});
		return dataVOS;
	}

	//大屏地图获取设备型号名
	private String getModelName(Long deviceModelId) {
		LambdaQueryWrapper<BasicDeviceModelEntity> lambdaQueryWrapper = Wrappers.lambdaQuery();
		lambdaQueryWrapper.eq(BasicDeviceModelEntity::getId, deviceModelId);
		List<BasicDeviceModelEntity> basicDeviceModelEntities = basicDeviceModelMapper.selectList(lambdaQueryWrapper);
		List<String> modelNames = basicDeviceModelEntities.stream().map(BasicDeviceModelEntity::getDeviceModelName).collect(Collectors.toList());

		String modelName = null;
		if (!modelNames.isEmpty()) {
			modelName = modelNames.get(0);
		}
		return modelName;

	}

	//获取坐标点故障记录
	private AlarmFaultLoggingEntity getPointFault(Long deviceId) {
		LambdaQueryWrapper<AlarmFaultLoggingEntity> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(AlarmFaultLoggingEntity::getDeviceId, deviceId);
		queryWrapper.orderByDesc(AlarmFaultLoggingEntity::getCreateTime);
		List<AlarmFaultLoggingEntity> list = alarmFaultLoggingService.listByScope(queryWrapper, new DataScope());

		if (!list.isEmpty()) {
			AlarmFaultLoggingEntity latestFault = list.get(0);
			return latestFault;
		}
		AlarmFaultLoggingEntity alarmFaultLogging = new AlarmFaultLoggingEntity();
		return alarmFaultLogging;
	}

	//获取坐标点报警记录
	private AlarmLoggingEntity getPointAlarm(Long deviceId) {
		LambdaQueryWrapper<AlarmLoggingEntity> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(AlarmLoggingEntity::getDeviceId, deviceId);
		queryWrapper.orderByDesc(AlarmLoggingEntity::getCreateTime);
		List<AlarmLoggingEntity> list = alarmLoggingService.listByScope(queryWrapper, new DataScope());

		if (!list.isEmpty()) {
			AlarmLoggingEntity latestAlarm = list.get(0);
			return latestAlarm;
		}
		AlarmLoggingEntity alarmLoggingEntity = new AlarmLoggingEntity();
		return alarmLoggingEntity;
	}

	//每日设备状态
	@Override
	public List<ScreenDeviceEventReportVO> deviceStateDay() {
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime startOfLastWeek = now.minusDays(7).withHour(0).withMinute(0).withSecond(0).withNano(0);

		LambdaQueryWrapper<DeviceEventReportEntity> lambdaQueryWrapper = Wrappers.lambdaQuery();
		lambdaQueryWrapper.between(DeviceEventReportEntity::getCreateTime, startOfLastWeek, now);
		List<DeviceEventReportEntity> reportEntities = deviceEventReportService.listByScope(lambdaQueryWrapper, new DataScope());
		Map<LocalDate, ScreenDeviceEventReportVO> resultMap = new LinkedHashMap<>();

		// 创建近七天的日期对象，并初始化统计值为 0
		for (int i = 0; i < 7; i++) {
			LocalDate date = now.minusDays(i).toLocalDate();
			ScreenDeviceEventReportVO vo = new ScreenDeviceEventReportVO();
			vo.setYear(date.getYear());
			vo.setMonth(date.getMonthValue());
			vo.setDay(date.getDayOfMonth());
			vo.setNormal(0);
			vo.setAlarm(0);
			vo.setFault(0);
			resultMap.put(date, vo);
		}

		// 统计数据
		for (DeviceEventReportEntity entity : reportEntities) {
			LocalDate date = LocalDate.of(entity.getYear(), entity.getMonth(), entity.getDay());
			ScreenDeviceEventReportVO vo = resultMap.computeIfAbsent(date, k -> {
				ScreenDeviceEventReportVO newVo = new ScreenDeviceEventReportVO();
				newVo.setYear(date.getYear());
				newVo.setMonth(date.getMonthValue());
				newVo.setDay(date.getDayOfMonth());
				newVo.setNormal(0);
				newVo.setAlarm(0);
				newVo.setFault(0);
				return newVo;
			});
			vo.setNormal(vo.getNormal() + (entity.getNormal() != null ? entity.getNormal() : 0));
			vo.setAlarm(vo.getAlarm() + (entity.getAlarm() != null ? entity.getAlarm() : 0));
			vo.setFault(vo.getFault() + (entity.getFault() != null ? entity.getFault() : 0));
			resultMap.put(date, vo);
		}

		// 将统计结果转换为列表
		List<ScreenDeviceEventReportVO> result = new ArrayList<>(resultMap.values());
		Collections.reverse(result);
		return result;
	}


	//每月设备状态
	@Override
	public List<ScreenDeviceEventReportVO> deviceStateMonth() {
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime startOfLastYear = now.minusMonths(11).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
		LambdaQueryWrapper<DeviceEventReportEntity> lambdaQueryWrapper = Wrappers.lambdaQuery();
		lambdaQueryWrapper.between(DeviceEventReportEntity::getCreateTime, startOfLastYear, now);

		List<DeviceEventReportEntity> reportEntities = deviceEventReportService.listByScope(lambdaQueryWrapper, new DataScope());

		Map<YearMonth, ScreenDeviceEventReportVO> resultMap = new LinkedHashMap<>();

		// 创建近 12 个月的日期对象，并初始化统计值为 0
		for (int i = 0; i < 12; i++) {
			YearMonth yearMonth = YearMonth.from(now.minusMonths(i));
			ScreenDeviceEventReportVO vo = new ScreenDeviceEventReportVO();
			vo.setYear(yearMonth.getYear());
			vo.setMonth(yearMonth.getMonthValue());
			vo.setNormal(0);
			vo.setAlarm(0);
			vo.setFault(0);
			resultMap.put(yearMonth, vo);
		}

		// 统计数据
		for (DeviceEventReportEntity entity : reportEntities) {
			YearMonth yearMonth = YearMonth.of(entity.getYear(), entity.getMonth());
			ScreenDeviceEventReportVO vo = resultMap.computeIfAbsent(yearMonth, k -> {
				ScreenDeviceEventReportVO newVo = new ScreenDeviceEventReportVO();
				newVo.setYear(yearMonth.getYear());
				newVo.setMonth(yearMonth.getMonthValue());
				newVo.setNormal(0);
				newVo.setAlarm(0);
				newVo.setFault(0);
				return newVo;
			});
			vo.setNormal(vo.getNormal() + (entity.getNormal() != null ? entity.getNormal() : 0));
			vo.setAlarm(vo.getAlarm() + (entity.getAlarm() != null ? entity.getAlarm() : 0));
			vo.setFault(vo.getFault() + (entity.getFault() != null ? entity.getFault() : 0));
		}

		// 将统计结果转换为列表
		List<ScreenDeviceEventReportVO> result = new ArrayList<>(resultMap.values());
		Collections.reverse(result);
		return result;
	}

	//产品分类占比
	@Override
	public List<ScreenDataVO> productClassification() {
		// 获取所有设备类型名称
		List<String> typeNameList = basicDeviceTypeService.getBaseMapper().selectList(Wrappers.lambdaQuery())
				.stream()
				.map(BasicDeviceTypeEntity::getTypeName)
				.collect(Collectors.toList());

		// 获取BasicDeviceEntity表中所有设备类型的id
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicDeviceEntity> list = basicDeviceService.listByScope(queryWrapper, new DataScope());
		List<Long> deviceId = list.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());

		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper();
		wrapper.in(BasicDeviceEntity::getId, deviceId);

		List<Long> typeIdList = basicDeviceService.list(wrapper)
				.stream()
				.map(BasicDeviceEntity::getDeviceTypeId)
				.collect(Collectors.toList());

		// 计算各个设备类型的数量和占比
		Map<String, Long> deviceTypeCountMap = typeIdList.stream()
				.collect(Collectors.groupingBy(
						id -> basicDeviceTypeService.getById(id).getTypeName(),
						Collectors.counting()
				));

		List<ScreenDataVO> screenDataList = new ArrayList<>();
		long totalDevices = typeIdList.size();
		//对百分比格式化
		DecimalFormat decimalFormat = new DecimalFormat("#.##");
		decimalFormat.setGroupingUsed(false);
		decimalFormat.setDecimalSeparatorAlwaysShown(true);
		for (String typeName : typeNameList) {
			long count = deviceTypeCountMap.getOrDefault(typeName, 0L);
			double percentage = (count * 100.0) / totalDevices;

			ScreenDataVO screenDataVO = new ScreenDataVO();
			screenDataVO.setProductName(typeName);
			screenDataVO.setProductCount(String.valueOf(count));
			screenDataVO.setProductPer(Double.parseDouble(decimalFormat.format(percentage)));
			screenDataList.add(screenDataVO);
		}
		return screenDataList;
	}

	@Override
	public List<ProductRotationVO> productRotation() {
		return basicDeviceService.productRotation();
	}

	@Override
	public Map<String, Long> faultCauseStatistics(AlarmFaultLoggingEntity alarmFaultLogging) {
		LambdaQueryWrapper<AlarmFaultLoggingEntity> wrapper = Wrappers.lambdaQuery(alarmFaultLogging);

		List<AlarmFaultLoggingEntity> alarmFaultLoggingEntities = alarmFaultLoggingService.listByScope(wrapper, new DataScope());
		if (ObjectUtil.isEmpty(alarmFaultLoggingEntities)) return new HashMap();
		Map<String, Long> statistics = alarmFaultLoggingEntities.stream()
				.collect(Collectors.groupingBy(AlarmFaultLoggingEntity::getEventTypeName, Collectors.counting()));
		return statistics;
	}


	public Map<String, Long> alarmAcknowledgement() {
		LambdaQueryWrapper<AlarmLoggingEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(AlarmLoggingEntity::getState, 10);
		List<AlarmLoggingEntity> todayAlarms = alarmLoggingService.listByScope(wrapper, new DataScope());
		if (ObjectUtil.isEmpty(todayAlarms)) return new HashMap<>();

		Map<String, Long> statistics = todayAlarms.stream()
				.collect(Collectors.groupingBy(AlarmLoggingEntity::getProcessTypeName, Collectors.counting()));
		return statistics;
	}

	//首页设备安装占比
	@Override
	public HomePageDataVO deviceInstallCount() {
		LambdaQueryWrapper<BasicDeviceEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicDeviceEntity> list = basicDeviceService.listByScope(queryWrapper, new DataScope());
		List<Long> deviceId = list.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());

		MPJLambdaWrapper<BasicDeviceEntity> wrapper = createBaseWrapper()
				.in(BasicDeviceEntity::getId, deviceId);
		List<BasicDeviceEntity> deviceEntities = basicDeviceMapper.selectList(wrapper);

		long cutboundCount = deviceEntities.stream()
				.filter(entity -> entity.getBindState() == 30)
				.count();
		long total = deviceEntities.size();
		long unCutBoundCount = total - cutboundCount;
		double cutboundCountPer = 0;
		double unCutboundCountPer = 0;
		if (total != 0) {
			cutboundCountPer = (cutboundCount * 100.0) / total;
			unCutboundCountPer = (unCutBoundCount * 100.0) / total;
		}

		DecimalFormat decimalFormat = new DecimalFormat("#.##");
		decimalFormat.setGroupingUsed(false);
		decimalFormat.setDecimalSeparatorAlwaysShown(true);

		HomePageDataVO homePageDataVO = new HomePageDataVO();

		homePageDataVO.setDeviceTotal(total);
		homePageDataVO.setCutboundCount(cutboundCount);
		homePageDataVO.setUnCutboundCount(unCutBoundCount);
		homePageDataVO.setCutboundCountPer(Double.parseDouble(decimalFormat.format(cutboundCountPer)));
		homePageDataVO.setUnCutboundCountPer(Double.parseDouble(decimalFormat.format(unCutboundCountPer)));

		return homePageDataVO;
	}


	@Override
	public JSONObject homeAlarmConfirmationType() {
		JSONObject jsonObject = new JSONObject();
		LambdaQueryWrapper<AlarmLoggingEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(AlarmLoggingEntity::getState, 10);
		List<AlarmLoggingEntity> alarmLoggingList = alarmLoggingService.listByScope(wrapper, new DataScope());
		if (ObjectUtil.isEmpty(alarmLoggingList)) return jsonObject;
		alarmLoggingList = alarmLoggingList.stream().filter(i -> ObjectUtil.isNotEmpty(i.getProcessTypeName())).collect(Collectors.toList());
		List<String> processTypeNameList = alarmLoggingList.stream().filter(i -> ObjectUtil.isNotEmpty(i.getProcessTypeName())).map(AlarmLoggingEntity::getProcessTypeName).distinct().collect(Collectors.toList());

		Map<String, List<AlarmLoggingEntity>> createTimeMap = alarmLoggingList.stream().collect(Collectors.groupingBy(x -> x.getProcessingTime().toLocalDate().toString()));
		List<String> createTime = alarmLoggingList.stream().map(x -> {
			return x.getProcessingTime().toLocalDate().toString();
		}).distinct().collect(Collectors.toList());

		HashMap<String, List> stringListHashMap = new HashMap<>();
		processTypeNameList.stream().forEach(x -> {

			stringListHashMap.put(x, new ArrayList());
		});

		createTimeMap.entrySet().stream().forEach(x -> {
			List<AlarmLoggingEntity> alarmLoggingEntities = createTimeMap.get(x.getKey());
			Map<String, Long> collect = alarmLoggingEntities.stream()
					.filter(i -> ObjectUtil.isNotEmpty(i.getEventTypeName()))
					.collect(Collectors.groupingBy(AlarmLoggingEntity::getProcessTypeName, Collectors.counting()));
			processTypeNameList.stream().forEach(i -> {
				List list = stringListHashMap.get(i);
				Long orDefault = collect.getOrDefault(i, 0L);
				list.add(orDefault);

			});

		});

		jsonObject.put("x", createTime);
		jsonObject.put("y", stringListHashMap);
		jsonObject.put("type", processTypeNameList);

		return jsonObject;
	}

	@Override
	public JSONObject abnormalStatistics() {
		List<Long> list = DataScopeUtils.getList();
		LambdaQueryWrapper<AlarmLoggingEntity> aleq = Wrappers.lambdaQuery(AlarmLoggingEntity.class)
				.eq(AlarmLoggingEntity::getState,20)
				.in(ObjectUtil.isNotEmpty(list), AlarmLoggingEntity::getDeptId, list);
		long alarmLoggingCount = alarmLoggingService.countByScope(aleq,new DataScope());
		LambdaQueryWrapper<AlarmFaultLoggingEntity> afeq = Wrappers.lambdaQuery(AlarmFaultLoggingEntity.class)
				.eq(AlarmFaultLoggingEntity::getState,20)
				.in(ObjectUtil.isNotEmpty(list), AlarmFaultLoggingEntity::getDeptId, list);
		long faultLoggingCount = alarmFaultLoggingService.countByScope(afeq,new DataScope());
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("alarmLoggingCount", alarmLoggingCount);
		jsonObject.put("faultLoggingCount", faultLoggingCount);

		return jsonObject;
	}

	@Override
	public ScreenDataVO getScreenDevice() {
		//大屏安装设备数
		LambdaQueryWrapper<BasicInstallLocationEntity> queryWrapper = Wrappers.lambdaQuery();
		List<BasicInstallLocationEntity> list = basicInstallLocationService.listByScope(queryWrapper, new DataScope());
		List<Long> installLocationId = list.stream().map(BasicInstallLocationEntity::getId).collect(Collectors.toList());
		long placeRoomCount = 0;
		if (ObjectUtil.isNotEmpty(installLocationId)) {
			MPJLambdaWrapper<BasicInstallLocationEntity> wrapper = createBaseInstallLocationWrapper();
			wrapper.in(BasicInstallLocationEntity::getId, installLocationId);

			List<BasicInstallLocationEntity> installLocationEntities = basicInstallLocationService.list(wrapper);

			if (ObjectUtil.isNotEmpty(installLocationEntities)) {
				placeRoomCount = installLocationEntities.size();
			}
		}

		//大屏设备在线数
		long deviceOnlineCount = 0;
		Long onlineCount = basicDeviceService.getDeviceOnlineCount();
		if (ObjectUtil.isNotNull(onlineCount)) {
			deviceOnlineCount = onlineCount;
		}

		//大屏设备离线数
		long deviceOfflineCount = 0;
		Long offlineCount = basicDeviceService.getDeviceOfflineCount();
		if (ObjectUtil.isNotNull(offlineCount)) {
			deviceOfflineCount = offlineCount;
		}

		//大屏下级设备数
		Long deptId = SecurityUtils.getUser().getDeptId();
		long lowerDeptCount = remoteDeptService.getDescendantList(deptId).getData().size() - 1;

		//大屏正常设备数
		long deviceNormalCount = 0;
		Long normalCount = basicDeviceService.getDeviceNormalCount();
		if (ObjectUtil.isNotNull(normalCount)) {
			deviceNormalCount = normalCount;
		}

		//大屏故障设备数
		long deviceFaultCount = 0;
		Long faultCount = basicDeviceService.getDeviceFaultCount();
		if (ObjectUtil.isNotNull(faultCount)) {
			deviceFaultCount = faultCount;
		}

		//大屏报警设备数
		long deviceAlarmCount = 0;
		Long alarmCount = basicDeviceService.getDeviceAlarmCount();
		if (ObjectUtil.isNotNull(alarmCount)) {
			deviceAlarmCount = alarmCount;
		}

		long total = deviceNormalCount + deviceFaultCount;
		double deviceNormalCountPer = 0;
		if (total != 0) {
			deviceNormalCountPer = (deviceNormalCount * 100) / total;
		}
		double deviceFaultCountPer = 0;
		if (total != 0) {
			deviceFaultCountPer = (deviceFaultCount * 100) / total;
		}

		//对百分比格式化
		DecimalFormat decimalFormat = new DecimalFormat("#.##");
		decimalFormat.setGroupingUsed(false);
		decimalFormat.setDecimalSeparatorAlwaysShown(true);

		ScreenDataVO screenDataVO = new ScreenDataVO();
		screenDataVO.setPlaceRoomCount(placeRoomCount);
		screenDataVO.setDeviceOnlineCount(deviceOnlineCount);
		screenDataVO.setDeviceOfflineCount(deviceOfflineCount);
		screenDataVO.setLowerDeptCount(lowerDeptCount);
		screenDataVO.setDeviceNormalCount(deviceNormalCount);
		screenDataVO.setDeviceFaultCount(deviceFaultCount);
		screenDataVO.setDeviceAlarmCount(deviceAlarmCount);
		screenDataVO.setDeviceNormalCountPer(Double.parseDouble(decimalFormat.format(deviceNormalCountPer)));
		screenDataVO.setDeviceFaultCountPer(Double.parseDouble(decimalFormat.format(deviceFaultCountPer)));

		return screenDataVO;
	}

	public ScreenDataVO getTodayFault() {
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime startOfDay = now.toLocalDate().atStartOfDay();
		LocalDateTime endOfDay = now.toLocalDate().atTime(23, 59, 59);

		LambdaQueryWrapper<AlarmFaultLoggingEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.between(AlarmFaultLoggingEntity::getCreateTime, startOfDay, endOfDay);
		List<AlarmFaultLoggingEntity> todayFaults = alarmFaultLoggingService.listByScope(wrapper, new DataScope());

		long todayFaultNum = 0;
		long todayFaultHandledNum = 0;
		if (!ObjectUtil.isEmpty(todayFaults)) {
			todayFaultNum = todayFaults.size();

			todayFaultHandledNum = todayFaults.stream()
					.filter(entity -> entity.getState() != null)
					.filter(entity -> entity.getState() != 20)
					.count();
		}

		long todayAlarmHandledPer = 0;
		if (todayFaultNum != 0) {
			todayAlarmHandledPer = (todayFaultHandledNum * 100) / todayFaultNum;
		}
		// 将百分比转换为字符串格式，并添加百分号
		String percentStr = String.format("%d%%", todayAlarmHandledPer);

		ScreenDataVO screenDataVO = new ScreenDataVO();
		screenDataVO.setTodayFaultNum(todayFaultNum);
		screenDataVO.setTodayFaultHandledNum(todayFaultHandledNum);
		screenDataVO.setTodayFaultHandledPer(percentStr);
		return screenDataVO;
	}

	public ScreenDataVO getTodayAlarm() {
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime startOfDay = now.toLocalDate().atStartOfDay();
		LocalDateTime endOfDay = now.toLocalDate().atTime(23, 59, 59);

		LambdaQueryWrapper<AlarmLoggingEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.between(AlarmLoggingEntity::getCreateTime, startOfDay, endOfDay);
		List<AlarmLoggingEntity> todayAlarms = alarmLoggingService.listByScope(wrapper, new DataScope());

		long todayAlarmNum = 0;
		long todayAlarmHandledNum = 0;
		if (!ObjectUtil.isEmpty(todayAlarms)) {
			todayAlarmNum = todayAlarms.size();

			todayAlarmHandledNum = todayAlarms.stream()
					.filter(entity -> entity.getState() != null)
					.filter(entity -> entity.getState() != 20)
					.count();
		}

		long todayAlarmHandledPer = 0;
		if (todayAlarmNum != 0) {
			todayAlarmHandledPer = (todayAlarmHandledNum * 100) / todayAlarmNum;
		}
		// 将百分比转换为字符串格式，并添加百分号
		String percentStr = String.format("%d%%", todayAlarmHandledPer);
		log.debug(percentStr);


		ScreenDataVO screenDataVO = new ScreenDataVO();
		screenDataVO.setTodayAlarmNum(todayAlarmNum);
		screenDataVO.setTodayAlarmHandledNum(todayAlarmHandledNum);
		screenDataVO.setTodayAlarmHandledPer(percentStr);
		return screenDataVO;
	}

	private MPJLambdaWrapper<BasicInstallLocationEntity> createBaseInstallLocationWrapper() {
		return new MPJLambdaWrapper<BasicInstallLocationEntity>()
				.selectAll(BasicInstallLocationEntity.class)
				.selectAs(BasicDeviceEntity::getInstallLocationId, BasicInstallLocationVO::getId)
				.selectAs(BasicDeviceEntity::getId, BasicInstallLocationVO::getDeviceId)
				.selectAs(BasicDeviceEntity::getDeptId, BasicInstallLocationVO::getDeptId)
				.selectAs(BasicDeviceEntity::getDeviceState, BasicInstallLocationVO::getDeviceState)
				.selectAs(BasicAlarmContactsEntity::getName, BasicInstallLocationVO::getAlarmWorkerName)
				.selectAs(BasicAlarmContactsEntity::getPhone, BasicInstallLocationVO::getAlarmWorkerPhone)

				.leftJoin(BasicDeviceEntity.class, BasicDeviceEntity::getInstallLocationId, BasicInstallLocationEntity::getId)
				.leftJoin(BasicAlarmContactsEntity.class, BasicAlarmContactsEntity::getId, BasicInstallLocationEntity::getAlarmWorkerId);
	}

	private MPJLambdaWrapper<BasicInstallLocationEntity> createScreenUnprocessedAlarmWrapper() {
		return new MPJLambdaWrapper<BasicInstallLocationEntity>()
				.selectAll(BasicInstallLocationEntity.class)

				.selectAs(BasicInstallLocationEntity::getAddress, ScreenDataVO::getAddress)
				.selectAs(BasicInstallLocationEntity::getDetailAddress, ScreenDataVO::getDetailAddress)
				.selectAs(BasicAlarmContactsEntity::getName, ScreenDataVO::getAlarmWorkerName)
				.selectAs(BasicAlarmContactsEntity::getPhone, ScreenDataVO::getPhone)
				.selectAs(AlarmLoggingEntity::getAlarmCauses, ScreenDataVO::getAlarmCauses)
				.selectAs(AlarmLoggingEntity::getImei, ScreenDataVO::getImei)
				.selectAs(AlarmLoggingEntity::getDeviceModelName, ScreenDataVO::getDeviceModelName)
				.selectAs(AlarmLoggingEntity::getCreateTime, ScreenDataVO::getAlarmCreateTime)
				.selectAs(AlarmLoggingEntity::getRemarks, ScreenDataVO::getRemarks)
				.selectAs(BasicInstallLocationEntity::getLongitude, ScreenDataVO::getLongitude)
				.selectAs(BasicInstallLocationEntity::getLatitude, ScreenDataVO::getLatitude)
				.eq(AlarmLoggingEntity::getState, 20)

				.leftJoin(BasicAlarmContactsEntity.class, BasicAlarmContactsEntity::getId, BasicInstallLocationEntity::getAlarmWorkerId)
				.leftJoin(AlarmLoggingEntity.class, AlarmLoggingEntity::getInstallLocationId, BasicInstallLocationEntity::getId);
	}

	private MPJLambdaWrapper<BasicInstallLocationEntity> createScreenUnprocessedFaultWrapper() {
		return new MPJLambdaWrapper<BasicInstallLocationEntity>()
				.selectAll(BasicInstallLocationEntity.class)

				.selectAs(BasicInstallLocationEntity::getAddress, ScreenDataVO::getAddress)
				.selectAs(BasicInstallLocationEntity::getDetailAddress, ScreenDataVO::getDetailAddress)
				.selectAs(BasicAlarmContactsEntity::getName, ScreenDataVO::getAlarmWorkerName)
				.selectAs(BasicAlarmContactsEntity::getPhone, ScreenDataVO::getPhone)
				.selectAs(AlarmFaultLoggingEntity::getAlarmCauses, ScreenDataVO::getFaultCauses)
				.selectAs(AlarmFaultLoggingEntity::getImei, ScreenDataVO::getImei)
				.selectAs(AlarmFaultLoggingEntity::getDeviceModelName, ScreenDataVO::getDeviceModelName)
				.selectAs(AlarmFaultLoggingEntity::getCreateTime, ScreenDataVO::getFaultCreateTime)
				.selectAs(AlarmFaultLoggingEntity::getRemarks, ScreenDataVO::getRemarks)
				.selectAs(BasicInstallLocationEntity::getLongitude, ScreenDataVO::getLongitude)
				.selectAs(BasicInstallLocationEntity::getLatitude, ScreenDataVO::getLatitude)
				.eq(AlarmFaultLoggingEntity::getState, 20)

				.leftJoin(BasicAlarmContactsEntity.class, BasicAlarmContactsEntity::getId, BasicInstallLocationEntity::getAlarmWorkerId)
				.leftJoin(AlarmFaultLoggingEntity.class, AlarmFaultLoggingEntity::getInstallLocationId, BasicInstallLocationEntity::getId);
	}

	private MPJLambdaWrapper<BasicDeviceEntity> createScreenMapPointWrapper() {
		return new MPJLambdaWrapper<BasicDeviceEntity>()
				.selectAll(BasicDeviceEntity.class)

				.selectAs(BasicInstallLocationEntity::getAddress, ScreenMapPointVO::getAddress)
				.selectAs(BasicInstallLocationEntity::getDetailAddress, ScreenMapPointVO::getDetailAddress)
				.selectAs(BasicAlarmContactsEntity::getName, ScreenMapPointVO::getAlarmWorkerName)
				.selectAs(BasicAlarmContactsEntity::getPhone, ScreenMapPointVO::getPhone)
				.selectAs(BasicInstallLocationEntity::getRemarks, ScreenMapPointVO::getRemarks)
				.selectAs(BasicInstallLocationEntity::getLongitude, ScreenMapPointVO::getLongitude)
				.selectAs(BasicInstallLocationEntity::getLatitude, ScreenMapPointVO::getLatitude)
				.selectAs(BasicPlaceFloorEntity::getFloorName, ScreenMapPointVO::getFloorName)
				.selectAs(BasicInstallLocationEntity::getId, ScreenMapPointVO::getInstallLocationId)
				.leftJoin(BasicInstallLocationEntity.class, BasicInstallLocationEntity::getId, BasicDeviceEntity::getInstallLocationId)
				.leftJoin(BasicPlaceFloorEntity.class, BasicPlaceFloorEntity::getId, BasicInstallLocationEntity::getFloorId)
				.leftJoin(BasicAlarmContactsEntity.class, BasicAlarmContactsEntity::getId, BasicInstallLocationEntity::getAlarmWorkerId);
	}

	private MPJLambdaWrapper<BasicDeviceEntity> createBaseWrapper() {
		//多表查询
		return new MPJLambdaWrapper<BasicDeviceEntity>()
				.selectAll(BasicDeviceEntity.class)
				.selectAs(BasicDeviceTypeEntity::getTypeName, BasicDeviceVO::getDeviceType)
				.selectAs(BasicDeviceModelEntity::getDeviceModelName, BasicDeviceVO::getDeviceModelName)
				.leftJoin(BasicDeviceTypeEntity.class, BasicDeviceTypeEntity::getId, BasicDeviceEntity::getDeviceTypeId)
				.leftJoin(BasicDeviceModelEntity.class, BasicDeviceModelEntity::getId, BasicDeviceEntity::getDeviceModelId);

	}

	//获取地图坐标的属性
	private String getDeviceAttribute(Long deviceTypeId) {
		MPJLambdaWrapper<BasicDeviceAttributeEntity> wrapper1 = new MPJLambdaWrapper<BasicDeviceAttributeEntity>()
				.selectAll(BasicDeviceAttributeEntity.class)
				.selectAs(BasicDeviceAttributeEntity::getAttributeName, "attributeName")
				.selectAs(BasicDeviceAttributeDataEntity::getValue, "value")
				.leftJoin(BasicDeviceAttributeDataEntity.class,
						BasicDeviceAttributeDataEntity::getAttributeId,
						BasicDeviceAttributeEntity::getId)
				.eq(BasicDeviceAttributeEntity::getDeviceTypeId, deviceTypeId);

		List<Map<String, Object>> resultList = basicDeviceAttributeMapper.selectMaps(wrapper1);

		StringBuilder resultBuilder = new StringBuilder();
		for (Map<String, Object> resultMap : resultList) {
			String attributeName = (String) resultMap.get("attributeName");
			Object value = resultMap.get("value");
			if (attributeName != null && value != null) {
				resultBuilder.append(attributeName).append(":").append(value).append(",");
			} else if (attributeName != null) {
				resultBuilder.append(attributeName).append(":null,");
			}
		}

		String result = resultBuilder.toString();
		if (!result.isEmpty()) {
			result = result.substring(0, result.length() - 1);
		}

		return result;

	}
}
